#include <iostream>
#include <string>
#include <utility>
#include <vector>

class DataSource
{
public:
    virtual void writeData(std::string data) = 0;
    virtual void readData() = 0;
};

class FileDataSource : public DataSource
{
private:
    std::string filename;
public:
    FileDataSource(std::string filename_)
    {
        filename = std::move(filename_);
    }
    void writeData(std::string data) override
    {
        std::cout<<"write data to file "<<filename<< ":"<<data<<std::endl;
    }
    void readData() override
    {

    }
};

class DataSourceDecorator : public DataSource
{
protected:
    DataSource* wrappee = nullptr;
public:
    DataSourceDecorator(DataSource* wrappee_)
    {
        wrappee = wrappee_;
    }
    virtual void writeData(std::string data) = 0;
    virtual void readData() = 0;
};

class EncryptionDecorator : public DataSourceDecorator
{
public:
    EncryptionDecorator(DataSource* wrappee_)
    :DataSourceDecorator(wrappee_)
    {

    }
    void writeData(std::string data) override
    {
        wrappee->writeData(encryption(data));
    }
    std::string encryption(std::string data)
    {
        return "[encryption] " + data;
    }
    void readData() override
    {

    }
};

class CompressionDecorator : public DataSourceDecorator
{
public:
    CompressionDecorator(DataSource* wrappee_)
            :DataSourceDecorator(wrappee_)
    {

    }
    void writeData(std::string data) override
    {
        wrappee->writeData(encryption(data));
    }
    std::string encryption(std::string data)
    {
        return "[compression] " + data;
    }
    void readData() override
    {

    }
};

int main() {
    DataSource *data = new FileDataSource("password.txt");
    data->writeData("MyPassword");

    EncryptionDecorator* encryption = new EncryptionDecorator(data);
    encryption->writeData("MyPassword");

    CompressionDecorator* compression = new CompressionDecorator(data);
    compression->writeData("MyPassword");
    return 0;
}



